package datastructure;

import java.util.ArrayList;

public class Rule {
	private NonTerminal nonTerminal;
	private ArrayList<Alternative> alternatives;

	private ArrayList<Term> starters = new ArrayList<Term>();
	private ArrayList<Term> followers = new ArrayList<Term>();

	public Rule() {
	}

	public Rule(NonTerminal nt, ArrayList<Alternative> a) {

		nonTerminal = nt;
		alternatives = a;
	}

	public NonTerminal getNonTerminal() {
		return nonTerminal;
	}

	public void setNonTerminal(NonTerminal nonTerminal) {
		this.nonTerminal = nonTerminal;
	}

	public ArrayList<Alternative> getAlternatives() {
		return alternatives;
	}

	public void setAlternatives(ArrayList<Alternative> alternatives) {
		this.alternatives = alternatives;
	}

	public ArrayList<Term> defineStarters() {
		// Maak lijst van welke je gehad hebt
		if (starters.isEmpty()) {
			for (Alternative a : alternatives) {
				a.defineStarters(this);
			}
		}
		return starters;
	}

	public ArrayList<Term> defineFollowers() {
		if (followers.size() == 0) {
			ArrayList<Rule> bnf = Grammatica.getInstance().getBnf();

			for (Rule r : bnf) {
				for (Alternative a : r.getAlternatives()) {
					int index = a.getTerms().indexOf(nonTerminal);
					if (index != -1) {
						boolean done = false;
						while (!done) {
							index++;
							Term term = a.getTerm(index);
							if (term != null) {
								if (term instanceof Terminal) {
									followers.add(term);
									done = true;
								} else {
									@SuppressWarnings("unchecked")
									ArrayList<Term> starters = (ArrayList<Term>) Grammatica
											.getInstance()
											.findRuleByTerm((NonTerminal) term)
											.getStarters().clone();
									Term empty = new Terminal("E");
									if (starters.contains(empty)) {
										starters.remove(empty);
									} else {
										done = true;
									}
									followers.addAll(starters);
								}
							} else {
								followers.addAll(r.defineFollowers());
								done = true;
							}
						}
					}
				}
			}
		}
		return followers;
	}

	public ArrayList<Term> getStarters() {
		return starters;
	}
	
	public ArrayList<Term> getFollowers() {
		return followers;
	}

	public void addToStarters(Term toAdd) {
		starters.add(toAdd);
	}

	public void addToStarters(ArrayList<Term> toAdd) {
		for (Term t : toAdd) {
			addToStarters(t);
		}
	}

	public String toString() {
		String s = nonTerminal.toString() + " ::= ";
		for (int i = 0; i < alternatives.size() - 1; i++) {
			s += alternatives.get(i).toString() + "| ";
		}
		s += alternatives.get(alternatives.size() - 1) + "\n";
		return s;
	}

	public String toStringStarters() {
		String s = "";
		for (Term t : starters) {
			s += t.toString() + " ";
		}
		return s;
	}

	public String toStringFollowers() {
		String s = "";
		for (Term t : followers) {
			s += t.toString() + " ";
		}
		return s;
	}
}
